<template>
  <div>
    <div class="b-table" style="border: 1px solid #e7e7eb; margin:15px;position: relative;overflow:hidden" ref="boxOne"  >
      <div class="table-wrapper has-sticky-header " :style="{'height':height}" ref="boxTwo" >
        <table class="table"  ref="gsTable" style="table-layout:fixed;display: block;outline: none;border:1px solid #fff;" tabindex='0'>
          <thead>
            <tr>
              <!-- @click="titleClick(s.value,index)" -->
              <th class="th" v-for="(s,index) in tableHead" :key="index" :class="gsTitle" :align="s.align" style="border: 1px solid #e7e7eb;"
              >
                {{s.name}}
                <span class="solt-box">
                  <i :class="[{
                    'caret' :true,
                    'solt-asce':true,
                    'solt-asce-isBtn':titleSoltObj.value == s.value && titleSoltObj.sort == 'asce' ? true : false
                  }]"></i>
                  <i :class="[{
                    'caret' :true,
                    'solt-desc':true,
                    'solt-desc-isBtn':titleSoltObj.value == s.value && titleSoltObj.sort == 'desc' ? true : false
                  }]"></i>
                </span>
              </th>
            </tr>
          </thead>
          
          <tbody>
            <tr v-for="(item,index) in tableData" :key="index" :class="setBodyClass && setBodyClass(index) ||setBodyCls(index)">
              <td class="td" v-for="(headItem,i) in tableHead" :key="i" :class="(index == focus.index && headItem.value==focus.key) ? 'tdfocus':false"
                @click="thClick($event,index,headItem.value)"
                @dblclick ="thDbClick($event,index,headItem.value)">
          
                <gs :html="headItem.template" :item="item" v-if="(index == focus.index && headItem.value==focus.key && focus.ifRender==true && headItem.template)"></gs>
     
                <!-- <input v-gsFocus autocomplete="on" class="input" v-model="item[headItem.value]" :type="headItem.format || 'text' " @input="inputChange(index,headItem.value,item[headItem.value])"
                v-else-if="(index == focus.index && headItem.value==focus.key && focus.ifRender==true && headItem.type == componentType.input)"></input> -->
                <gs-input v-model="item[headItem.value]" :type="headItem.format || 'text' " @input.native="inputChange(index,headItem.value,item[headItem.value])"
                placeholder="" select :icon="headItem.icon" v-gsrender
                v-else-if="(index == focus.index && headItem.value==focus.key && focus.ifRender==true && headItem.type == componentType.input)"> 
                </gs-input>
  
                <!-- <input v-gsFocus autocomplete="on" class="input" v-model="item[headItem.value]" type="date" max="9999-12-31" 
                v-else-if="(index == focus.index && headItem.value==focus.key && focus.ifRender==true && headItem.type == componentType.date)"></input> -->
                <gs-date v-else-if="(index == focus.index && headItem.value==focus.key && focus.ifRender==true && headItem.type == componentType.date)"
                v-model="item[headItem.value]" :gsStyle="gsStyle || 'primary'"></gs-date>

                <div :style="{'width':headItem.width,'height':tableRowHeight + 'px'}" v-else-if="(headItem.type == componentType.button)">
                  <gs-button :type="headItem.btnType" :size="headItem.size" :circle="headItem.circle" style="transform:translate(0,-15%)" 
                  :disabled="!headItem.disabled(index,headItem)">
                    <i :class="headItem.icon"></i>
                    <!-- <span>{{headItem.name}}</span> -->
                  </gs-button> 
                </div>
              
                <gs-select v-model="item[headItem.value]" :options="headItem.options" trends="drop" :gsStyle="gsStyle" :disabled="!headItem.disabled(index,headItem)"
                v-else-if="(index == focus.index && headItem.value==focus.key && focus.ifRender==true && headItem.type == componentType.select)"></gs-select>

                <div v-html="headItem.type=='select' ? getSelectName(headItem.options,item[headItem.value]) : item[headItem.value]" 
                class="ell" :style="{'width':headItem.width,'height':tableRowHeight + 'px'}" v-else></div> 
                
              </td> 
            </tr>
            <!-- 填充合计行绝对定位 -->
            <tr v-if="summary" v-show="false">
              <td class="td">
                <div v-html="''" class="ell" :style="{'height':tableRowHeight + 'px'}"></div> 
              </td>
            </tr>


            <tr ref="bootomSum" v-if="summary" :style="[{
              'position':'absolute',
                'top':bootomfixed.top + 'px',
                'left':bootomfixed.left + 'px',
                'background': '#ffdd57',
                'z-index':'999'
              }]" >
              <td v-for="(item,index) in bottomData" :key="index" class="td"> 
                <div v-html="item.value" :style="{'width':item.width,'height':tableRowHeight + 'px'}" class="ell"></div> 
              </td>
            </tr>
            
          </tbody>
          
        </table>
        
      </div>
      <!-- 合计行 -->
        <!-- <table class="table" >
          <tbody ref="bootomSum" v-if="summary" :style="[{
            'position':'absolute',
              'top':bootomfixed.top + 'px',
              'left':bootomfixed.left + 'px',
              'background': '#ffdd57',
              'z-index':'999'
            }]">
            <tr >
              <td v-for="(item,index) in bottomData" :key="index" style="padding: .2em .35em;">
               
                <div v-html="item.value" :style="{'width':item.width,'height':tableRowHeight + 'px','box-sizing': 'border-box!important'}"></div> 
              </td>
            </tr>
          </tbody>
        </table>  -->
        
   
      
    </div>
    <!-- <button class="button is-primary" @click="test2"><span>西乡隆盛</span></button> -->
  </div>
</template>

<script>
import Vue from "vue";
import gsSelect from "../select/select";
import gsButton from "../button/button";
import gsInput from "../input/input";
import gsDate from '../date/date';
export default {
  /**
   *
   */
  name: "gsTable",
  components: {
    gsSelect,
    gsButton,
    gsInput,
    gsDate,
    gs: {
      props: {
        html: String,
        item: Object,
      },
      render(h) {
        const com = Vue.extend({
          template: this.html,
          props: {
            item: Object,
          },
        });
        return h(com, {
          props: {
            item: this.item,
          },
        });
      },
    },
  },
  props: {
    tableHead: Array,
    tableData: Array,
    //修改行样式
    setBodyClass: Function,
    //高度
    height: String,
    //是否显示合计行
    summary: Boolean,
    //风格
    gsStyle:String
  },
  data() {
    return {
      //焦点单元格
      focus: { index: 0, key: "", ifRender: false },
      //标题样式
      gsTitle: "gs-title",
      //表格样式
      gsBody: "gs-body",
      //排序字段
      titleSoltObj: { value: "", sort: true },
      //可以使用的插件类型
      componentType: {
        input: "input",
        date: "date",
        select: "select",
        button: "button",
      },
      //合计数据
      bottomData: [],
      //合计行定位
      bootomfixed: {
        top: Number(this.height.replace(/[^0-9]/gi, "")) - this.tableRowHeight - 20,
        // bottom:17,
        left: 0,
        // right: 400,
      },
      //行高度
      tableRowHeight:20,
      //下方滚动条厚度
      scrollWidth : 35,
      //是否获得焦点
      tableFocus:false
    };
  },
  created() {
    this.defaultWidth(() => {
      if (this.summary) this.initBottomData();
    });
  },
  mounted() {
    // const that = this
    //拦截按键
    this.setKeyup();
    //更新
    this.$nextTick(function () {
      this.$forceUpdate();
    });
    //设置滚动条
    if (this.summary) this.bindEvents();
    //添加表头拖动
    this.titleMove();
    //获取下方滚动条厚度
    this.initBottomMoble();
  },
  computed: {
  },
  methods: {
    //select 通过value 获取name 这个方法使用很频繁，后期可能要废弃
    getSelectName(options,value){
      const obj =  options.find((item)=>{if(item.value ==value) return item})
      if(obj)return obj.name
    },
    //获取下方滚动条厚度
    initBottomMoble(){
      // this.bootomfixed.top = Number(this.height.replace(/[^0-9]/gi, "")) - this.tableRowHeight - 20
      const { boxTwo } = this.$refs;
      let width = boxTwo.scrollWidth > boxTwo.clientWidth ? 25 : 15;
      this.bootomfixed.top = Number(this.height.replace(/[^0-9]/gi, "")) + boxTwo.scrollTop - this.tableRowHeight - width;
    },
    //初始化表格宽度
    defaultWidth(cellback) {
      this.tableHead.map((item) => {
        if (!item.width) {
          Vue.set(item, "width", this.getStringLong(item));
        }
      });
      cellback();
    },
    //获取字段的宽度
    getStringLong(item) {
      // let obj = Object.assign([], this.tableData);
      let obj = JSON.parse(JSON.stringify(this.tableData));
      let len = obj.sort(function (a, b) {
        return b[item.value] - a[item.value];
      })[0];
      
      if (typeof len[item.value] == "number") return "100px";
      else {
        if ((String(len[item.value]).length * 15) <= 100) {
          return "100px";
        } else {
          return String(String(len[item.value]).length * 15) + "px";
        }
      }
    },
    //获取表头row
    getTableHeadRow(key) {
      for (let index = 0; index < this.tableHead.length; index++) {
        if (this.tableHead[index].value == key) return this.tableHead[index];
      }
      return false;
    },
    //获取是否有合计
    getIfSum(key) {
      const row = this.getTableHeadRow(key);
      if (row.value == key && row.summary) return true;
      else return false;
    },
    //录入属性发生变化
    inputChange(index, key) {
      if (this.getIfSum(key)) this.setBottomSum(key);
    },
    //初始化表尾
    initBottomData() {
      this.bottomData = JSON.parse(JSON.stringify(this.tableHead));
      this.bottomData.map((item) => {
        item.name = item.value;
        item.value = item.format && item.format == "number" ? 0 : "";
      });
      this.bottomData[0].value = "合计:";
      this.setBottomSum();
    },
    //计算表尾合计
    setBottomSum(key) {
      const sumFn = (val) => {
        let sum = 0.0;
        for (let i = 0; i < this.tableData.length; i++) {
          sum += Number(this.tableData[i][val]) ?Number(this.tableData[i][val]) : 0 ;
        }
        return sum;
      };
      this.bottomData.map((item) => {
        if (key && item.summary) {
          item.value = sumFn(item.name);
          return;
        } else {
          if (item.summary) item.value = sumFn(item.name);
        }
      });
    },
    //点击标题触发
    titleClick(value) {
      this.titleSoltObj.value = value;
      this.titleSoltObj.sort && this.titleSoltObj.sort == "asce"
        ? (this.titleSoltObj.sort = "desc")
        : (this.titleSoltObj.sort = "asce");
      this.dataSort(value, this.titleSoltObj.sort);
      this.$emit("tableHeadClick", { value });
    },
    //数据排序
    dataSort(value, sort) {
      if (sort == "asce") {
        this.tableData.sort(function (y, x) {
          if (typeof x[value] == "string")
            return x[value].localeCompare(y[value]);
          if (typeof x[value] == "number") return x[value] - y[value];
        });
      } else {
        this.tableData.reverse(function (y, x) {
          if (typeof x[value] == "string")
            return x[value].localeCompare(y[value]);
          if (typeof x[value] == "number") return x[value] - y[value];
        });
      }
    },
    //拦截按键 @keyup.ctrl.37
    setKeyup() {
      this.$refs.gsTable.onkeydown = (e) => {
      this.$refs.gsTable.focus();
      return this.keyup(e)
      }
    },
    //监听按键
    keyup(keyCode) {
      for (let index = 0; index < this.tableHead.length; index++) {
        if (this.tableHead[index].value == this.focus.key) {
          switch (keyCode.key) {
            case "ArrowRight":
              if (this.tableHead[index + 1]) {
                return this.setFocusKey(this.tableHead[index + 1].value);
              }
              break;
            case "Enter":
              if (this.tableHead[index + 1]) {
                return this.setFocusKey(this.tableHead[index + 1].value);
              }
              break;
            case "Tab":
              if (this.tableHead[index + 1]) {
                return this.setFocusKey(this.tableHead[index + 1].value);
              }
              break;
            case "ArrowLeft" || "Enter":
              if (this.tableHead[index - 1]) {
                return this.setFocusKey(this.tableHead[index - 1].value);
              }
              break;
            case "ArrowUp":
              if (
                typeof this.focus.index == "number" &&
                this.focus.index != 0
              ) {
                this.focus.index--;
                return false;
              }
              break;
            case "ArrowDown":
              if (
                typeof this.focus.index == "number" &&
                this.focus.index != this.tableData.length - 1
              ) {
                this.focus.index = this.focus.index + 1;
                return false;
              }
              break;
            case "Insert":
              this.focus.ifRender = true;
              break;
            case "F2":
              this.focus.ifRender = true;
              break;
            default:
              return true;
          }
        }
      }
    },
    setFocusKey(val) {
      this.focus.key = val;
      // this.focus.ifRender=false;
      return false;
    },
    //默认设置行样式
    setBodyCls(i) {
      return i % 2 == 0 ? "warning-row" : "warning-rows";
    },
    //双击打开渲染
    thDbClick() {
      this.focus.index = arguments[1];
      this.focus.key = arguments[2];
      this.focus.ifRender = true;
    },
    //单击设置选中
    thClick() {
      if (this.focus.index == arguments[1] && this.focus.key == arguments[2])
        return;
      this.focus.index = arguments[1];
      this.focus.key = arguments[2];
      // this.focus.ifRender = false;
    },
    //修改表头样式
    setTitleClass(newClass) {
      this.gsTitle = newClass;
    },
    //拖动表格
    titleMove(){
      var tTD;
      var table = this.$refs.gsTable;
      var that = this
      var ifMove = false
      for (let j = 0; j < table.rows[0].cells.length; j++) {
        table.rows[0].cells[j].onmousedown = function () {
          ifMove = false
          //记录单元格
          tTD = this;
          if (event.offsetX > tTD.offsetWidth - 15) {
            tTD.mouseDown = true;
            tTD.oldX = event.x;
            tTD.oldWidth = tTD.offsetWidth;
          }
        };
        table.rows[0].cells[j].onmouseup = function () {
          if(ifMove == false) that.titleClick(that.tableHead[j].value);
          //结束宽度调整
          if (tTD == undefined) tTD = this;
          tTD.mouseDown = false;
          tTD.style.cursor = "default";
        };
        table.rows[0].cells[j].onmousemove = function () {
          ifMove = true;
          //更改鼠标样式
          if (event.offsetX > this.offsetWidth - 10) this.style.cursor = "col-resize";
          else this.style.cursor = "default";
          //取出暂存的Table Cell
          if (tTD == undefined) tTD = this;
          //调整宽度
          if (tTD.mouseDown != null && tTD.mouseDown == true) {
            tTD.style.cursor = "default";
            if (tTD.oldWidth + (event.x - tTD.oldX) > 0)
              tTD.width = tTD.oldWidth + (event.x - tTD.oldX);
            //调整列宽
            tTD.style.width = tTD.width;
            tTD.style.cursor = "col-resize";
            //调整该列中的每个Cell
            that.tableHead[tTD.cellIndex].width = tTD.width + "px"
            that.bottomData[tTD.cellIndex].width = tTD.width + "px"
          }
        };
      }
    },
    //添加监听
    bindEvents() {
      this.$refs.boxTwo.addEventListener(
        "scroll",
        () => {
          const { boxTwo } = this.$refs;
          let width = boxTwo.scrollWidth > boxTwo.clientWidth ? 25 : 15;
          this.bootomfixed.top = Number(this.height.replace(/[^0-9]/gi, "")) + boxTwo.scrollTop - this.tableRowHeight - width;
        },
        { passive: true }
      );
      
    },
  },
};
//<style lang="scss" src='../style/table.scss'></style>
</script>


